<?php

class Request
{

    /**
     * @var array
     */
    protected $_params = array();

    /**
     * @var string
     */
    protected $_method = 'GET';

    /**
     * handler id
     * @var string
     */
    protected $_handlerId = null;

    /**
     * constructor
     * @return void
     */
    public function __construct($params = null)
    {
        $params && $this -> setParams($params);
    }

    /**
     * magic get method
     * @param string $name
     * @return mixed
     */
    public function __get($name)
    {
        return isset($this -> _params[$name]) ? $this -> _params[$name] : null;
    }

    /**
     * @param string $name
     * @param mixed $value
     * @return $value;
     */
    public function __set($name, $value)
    {
        return $this -> _params[$name] = $value;
    }

    /**
     * @return string
     */
    public function getMethod()
    {
        return $this -> _method;
    }

    /**
     * set method name
     * @param string $method
     * @return Request
     */
    public function setMethod($method)
    {
        $this -> _method = strtoupper($method);
        return $this;
    }

    /**
     * @return bool
     */
    public function isGet()
    {
        return $this -> getMethod() == 'GET';
    }

    /**
     * @return bool
     */
    public function isPost()
    {
        return $this -> getMethod() == 'POST';
    }

    /**
     * @param string $key
     * @param mixed $default_value
     * @return Request
     */
    public function getParam($key, $default_value = null)
    {
        return isset($this -> _params[$key]) ? $this -> _params[$key] : $default_value;
    }

    /**
     * set param
     * @param string $key
     * @param mixed  $value
     * @return Request
     */
    public function setParam($key, $value)
    {
        $this -> _params[$key] = $value;
        return $this;
    }

    public function setParams($array)
    {
        foreach ($array as $key => $value)
        {
            $this -> _params[$key] = $value;
        }
        return $this;
    }

    /**
     * set handler
     * @example
     * 1. setHandler('core@index:index',[array('')])
     */
    public function setHandlerId($hanlderId)
    {
        $this -> _handlerId = $hanlderId;
        return $this;
    }

    /**
     * process handler id
     */
    public function getHandlerId()
    {
        return $this -> _handlerId;
    }

    /**
     * execute by handler
     */
    public function execute($response = null)
    {
        if (null == $response)
        {
            $response = new Response;
        }

        list($class, $action) = explode(':', $this -> _handlerId);

        // explode controller name
        $object = Agis::getResource($class, 'controller');

        $script = '/module/' . str_replace(array(
            '@',
            ".",
            ':'
        ), array(
            "/views/",
            "/",
            "/"
        ), $this -> _handlerId) . '.tpl';

        /**
         * preset response script
         */
        $response -> setScript($script);

        // execute request
        $object -> {'action' . inflect($action)}($this, $response);

        return $response -> execute();
    }

    /**
     * Retrieve a member of the $_COOKIE superglobal
     *
     * If no $key is passed, returns the entire $_COOKIE array.
     *
     * @todo How to retrieve from nested arrays
     * @param string $key
     * @param mixed $default Default value to use if key not found
     * @return mixed Returns null if key does not exist
     */
    static public function getCookie($key = null, $default = null)
    {
        return null === $key ? $_COOKIE : (isset($_COOKIE[$key]) ? $_COOKIE[$key] : $default);
    }

    /**

     * @param string $key
     * @param string $default
     * @return string
     */
    static public function getServer($key = null, $default = null)
    {
        return null === $key ? $_SERVER : (isset($_SERVER[$key])) ? $_SERVER[$key] : $default;
    }

    /**
     * @param string $key
     * @param string $default
     * @return string
     */
    static public function getEnv($key = null, $default = null)
    {
        return null === $key ? $_ENV : (isset($_ENV[$key])) ? $_ENV[$key] : $default;
    }

    /**
     * @param string $key
     * @return string
     */
    static public function getHeader($key)
    {

        // Try to get it from the $_SERVER array first
        $temp = 'HTTP_' . strtoupper(str_replace('-', '_', $key));

        if (isset($_SERVER[$temp]))
        {
            return $_SERVER[$temp];
        }

        if (function_exists('apache_request_headers'))
        {
            $headers = apache_request_headers();
            if (isset($headers[$key]))
            {
                return $headers[$key];
            }
            $header = strtolower($key);
            foreach ($headers as $k => $v)
            {
                if (strtolower($k) == $key)
                {
                    return $value;
                }
            }
        }

        return false;
    }

    /**
     * @return string
     */
    static public function getScheme()
    {
        return self::getServer('HTTPS') == 'on' ? 'https' : 'http';
    }

    /**
     * Get the HTTP host.
     *
     * "Host" ":" host [ ":" port ] ; Section 3.2.2
     * Note the HTTP Host header is not the same as the URI host.
     * It includes the port while the URI host doesn't.
     *
     * @return string
     */
    static public function getHttpHost()
    {
        $host = self::getServer('HTTP_HOST');

        if (!empty($host))
        {
            return $host;
        }

        $scheme = self::getScheme();
        $name = self::getServer('SERVER_NAME');
        $port = self::getServer('SERVER_PORT');

        if (null === $name)
        {
            return '';
        }
        elseif (($scheme == 'http' && $port == 80) || ($scheme == 'https' && $port == 443))
        {
            return $name;
        }
        else
        {
            return $name . ':' . $port;
        }
    }

    /**
     * @return string
     */
    static public function getClientIp()
    {
        if (self::getServer('HTTP_CLIENT_IP'))
        {
            self::getServer('HTTP_CLIENT_IP');
        }

        if (self::getServer('HTTP_X_FORWARDED_FOR'))
        {
            return self::getServer('HTTP_X_FORWARDED_FOR');
        }

        return self::getServer('REMOTE_ADDR', '127.0.0.1');
    }

    /**
     * Is https secure request
     *
     * @return boolean
     */
    static public function isSecure()
    {
        return (self::getScheme() === 'https');
    }

    /**
     *
     * @return boolean
     */
    static public function isFlash()
    {
        return strpos(self::getHeader('USER_AGENT'), ' flash') !== false;
    }

    /**
     * Is the request a Javascript XMLHttpRequest?
     *
     * Should work with Prototype/Script.aculo.us, possibly others.
     *
     * @return boolean
     */
    static public function isAjax()
    {
        return (self::getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
    }

}
